package view;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import worldModel.*;
import battleFieldModel.*;

/**
 * JavaBoy 9
 * 
 * @author Gopal Adhikari, Alex James Topping
 * @version 9
 * 
 */

/**
 * WorldView GUI provider for JavaBoy. This class encapsulates MasterView,
 * Navigator and World classes in to it and provides a graphical view for each.
 * 
 */
public class WorldView extends MasterViewPanel implements Observer {

	private static final long serialVersionUID = -629796683513197443L;

	private Navigator nav;
	private Image floorTile;
	private MasterView m;
	private World world;
	private BufferedImage navigatorSpriteSheet;

	static int offSetX = 0;
	static int offSetY = 0;

	public WorldView(MasterView m, Navigator n) {

		super(m);
		this.m = m;
		this.nav = n;
		this.world = new World(this.nav);

		try {
			floorTile = new ImageIcon("images/floorPanel.png").getImage();
			navigatorSpriteSheet = ImageIO
					.read(new File("images/navigator.png"));
		} catch (Exception ex) {
			System.out.println("floorPanel.png or navigator.png not found!");
		}

		KeyListener key = new KeyListener() {

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
			}

			@Override
			public void keyPressed(KeyEvent e) {
				try {
					int keyCode = e.getKeyCode();
					if (keyCode == KeyEvent.VK_DOWN) {
						offSetY = 0;
						offSetX += 32;
						offSetX = (offSetX == 96) ? 0 : offSetX;
						world.move(Direction.SOUTH_EAST);
						repaint();
					}

					else if (keyCode == KeyEvent.VK_UP) {
						offSetX += 32;
						offSetX = (offSetX == 96) ? 0 : offSetX;
						offSetY = 96;
						world.move(Direction.NORTH_WEST);
						repaint();
					}

					else if (keyCode == KeyEvent.VK_LEFT) {
						offSetX += 32;
						offSetX = (offSetX == 96) ? 0 : offSetX;
						offSetY = 32;
						world.move(Direction.SOUTH_WEST);
						repaint();
					}

					else if (keyCode == KeyEvent.VK_RIGHT) {
						offSetX += 32;
						offSetX = (offSetX == 96) ? 0 : offSetX;
						offSetY = 64;
						world.move(Direction.NORTH_EAST);
						repaint();

					} else if (keyCode == KeyEvent.VK_X) {

						List<Item> smallHealItems = new ArrayList<Item>();
						List<Item> mediumHealItems = new ArrayList<Item>();
						List<Item> largeHealItems = new ArrayList<Item>();
						//
						// smallHealItems.add(new SmallHeal());
						// smallHealItems.add(new SmallHeal());
						// smallHealItems.add(new SmallHeal());

						for (Item item : nav.getInventory()) {
							if (item.toString().equals("SmallHeal")) {
								System.out.println("Added small heal.");
								smallHealItems.add(item);
							} else if (item.toString().equals("MediumHeal")) {
								mediumHealItems.add(item);
							} else if (item.toString().equals("LargeHeal")) {
								largeHealItems.add(item);
							}
						}

						int smallCount = smallHealItems.size();
						int mediumCount = mediumHealItems.size();
						int largeCount = largeHealItems.size();

						String dialogTitle = "Player Health: "
								+ nav.getPlayer().getHealth();

						List<String> optionsList = new ArrayList<String>();

						optionsList.add("Small Heal (" + smallCount + ")");

						optionsList.add("Medium Heal (" + mediumCount + ")");

						optionsList.add("Large Heal (" + largeCount + ")");

						Object[] options = { optionsList.get(0),
								optionsList.get(1), optionsList.get(2),
								"Quit Game", "Back to Game" };

						int response = JOptionPane.showOptionDialog(null,
								"What would you like to do?", dialogTitle,
								JOptionPane.DEFAULT_OPTION,
								JOptionPane.QUESTION_MESSAGE, null, options,
								options[0]);

						/*
						 * The response keeps tracks of the user's choice from
						 * the option dialog box. If response = 0: Small Heal If
						 * response=4 :Back to game
						 */

						switch (response) {
						case 0:
							if (smallCount != 0) {
								if (nav.getPlayer().getHealth() < 100) {
									smallHealItems.get(0).activateEffect(nav);
									smallHealItems.remove(0);
									smallCount--;
								} else {
									JOptionPane
											.showMessageDialog(null,
													"Your health is already maxed out, N00B!");
								}
							}
							break;
						case 1:
							if (mediumCount != 0) {
								if (nav.getPlayer().getHealth() < 100) {
									mediumHealItems.get(0).activateEffect(nav);
									mediumHealItems.remove(0);
									mediumCount = mediumHealItems.size();
								} else {
									JOptionPane
											.showMessageDialog(null,
													"Your health is already maxed out, N00B!");
								}
							}
							break;
						case 2:
							if (largeCount != 0) {
								if (nav.getPlayer().getHealth() < 100) {
									largeHealItems.get(0).activateEffect(nav);
									largeHealItems.remove(0);
									largeCount = largeHealItems.size();
								} else {
									JOptionPane
											.showMessageDialog(null,
													"Your health is already maxed out, N00B!");
								}
							}
							break;

						case 3:
							saveGame();
							System.exit(0);
							break;
						case 4:
							break;
						}

						nav.getInventory().clear();

						List<Item> itemsToAddAgain = new ArrayList<Item>();
						itemsToAddAgain.addAll(smallHealItems);
						itemsToAddAgain.addAll(mediumHealItems);
						itemsToAddAgain.addAll(largeHealItems);

						for (Item i : itemsToAddAgain) {
							nav.addItem(i);
						}
						SaveGameHelper.saveGame(nav);
					}

				} catch (Exception ex) {
					ex.printStackTrace();
				}

			}

			private void saveGame() {
				SaveGameHelper.saveGame(nav);
			}
		};

		this.addKeyListener(key);
		world.addObserver(this);
		this.setFocusable(true);
	}

	@Override
	protected void paintComponent(Graphics g) {

		super.paintComponent(g);
		Graphics2D g2d = (Graphics2D) g;
		Iterator<WorldTile> worldTileItr = world.tiles(nav.getLocation());

		while (worldTileItr.hasNext()) {

			WorldTile tile = worldTileItr.next();

			int r = nav.getLocation().row - tile.getLocation().row;
			int c = nav.getLocation().col - tile.getLocation().col;

			int x = 280 + (32 * r) - (32 * c) + nav.getLeeway().row
					- nav.getLeeway().col;
			int y = 170 - (32 * c) - (32 * r) - nav.getLeeway().row
					- nav.getLeeway().col;

			g.drawImage(floorTile, x, y, null);

		}

		g2d.drawImage(
				navigatorSpriteSheet.getSubimage(offSetX, offSetY, 32, 32),
				306, 151, 32, 32, null);
	}

	@Override
	public void update(Observable o, Object arg) {
		if (arg == null) {
			this.repaint();
		} else if (arg instanceof BattleField) {
			m.changeView(Views.BATTLE, arg);
		} else if (arg == Views.PREVIOUS) {
			m.changeView(Views.PREVIOUS, null);
		}
	}

}